﻿/* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 
Copyright (C) 2010 by Tomasz Pluskiewicz

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */

using System.Collections.Generic;
using Yama.MVC.Core.Models;

namespace Yama.MVC.Dao.Repositories
{
    /// <summary>
    /// Database column sord order
    /// </summary>
    public enum SortDirection
    {
        /// <summary>
        /// Ascending order
        /// </summary>
        Ascending,
        /// <summary>
        /// Descending order
        /// </summary>
        Descending
    }

    /// <summary>
    /// A marker interface base for <see cref="IDao{TId, T}"/>
    /// </summary>
    public interface IDao
    {
        int BatchSize { set; }
        void ClearAndFlushSession();
    }

    /// <summary>
    /// Defines base functionality for repositories
    /// </summary>
    /// <typeparam name="TId">Entity's key type</typeparam>
    /// <typeparam name="T"><see cref="Entity{TId}"/> type</typeparam>
    public interface IDao<TId, T> : IDao where T : Entity<TId>
    {
        /// <summary>
        /// Gets an entity from database based on it's primary key
        /// </summary>
        T FindById(TId identity);

        /// <summary>
        /// Saves a new instance to database or updates an existing row
        /// </summary>
        T Save(T instance);

        /// <summary>
        /// Deletes all instances of <see cref="T"/>
        /// </summary>
        void DeleteAll();

        /// <summary>
        /// Saves or updates all instances from list
        /// </summary>
        /// <param name="instance">list of <see cref="T"/> instances</param>
        void SaveAll(IList<T> instance);

        /// <summary>
        /// Updates an instance
        /// </summary>
        void Update(T instance);

        /// <summary>
        /// Loads an instance from database but does not initialize any of it's properties
        /// </summary>
        /// <returns></returns>
        T Load(TId identity);

        #region Count

        /// <summary>
        /// Returns count of <see cref="T"/> objects stored in database
        /// </summary>
        long Count();

        /// <summary>
        /// Returns count of <see cref="T"/> objects stored in database
        /// </summary>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        long Count(IDictionary<string, object> propertyValuePairs);

        #endregion

        #region FindAll

        ///<summary>
        /// Returns all instances of <see cref="T"/> stored in database. This method should not be used
        /// too often. If used, consider using PagedFind instead. See more on http://nhprof.com/Learn/Alerts/UnboundedResultSet
        ///</summary>
        ///<returns>A list of <see cref="T"/> objects</returns>
        IList<T> FindAll();

        ///<summary>
        /// Returns all instances of <see cref="T"/> stored in database. This method should not be used
        /// too often. If used, consider using PagedFind instead. See more on http://nhprof.com/Learn/Alerts/UnboundedResultSet
        ///</summary>
        ///<returns>A list of <see cref="T"/> objects</returns>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        IList<T> FindAll(IDictionary<string, object> propertyValuePairs);

        ///<summary>
        /// Returns all instances of <see cref="T"/> stored in database. This method should not be used
        /// too often. If used, consider using PagedFind instead. See more on http://nhprof.com/Learn/Alerts/UnboundedResultSet
        ///</summary>
        ///<returns>A list of <see cref="T"/> objects</returns>
        /// <param name="propertyOrderPairs">property name/<see cref="SortDirection"/> pairs which allow ordering</param>
        IList<T> FindAll(IDictionary<string, SortDirection> propertyOrderPairs);

        ///<summary>
        /// Returns all instances of <see cref="T"/> stored in database. This method should not be used
        /// too often. If used, consider using PagedFind instead. See more on http://nhprof.com/Learn/Alerts/UnboundedResultSet
        ///</summary>
        ///<returns>A list of <see cref="T"/> objects</returns>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        /// <param name="propertyOrderPairs">property name/<see cref="SortDirection"/> pairs which allow ordering</param>
        IList<T> FindAll(IDictionary<string, object> propertyValuePairs, IDictionary<string, SortDirection> propertyOrderPairs);

        #endregion

        #region FindFirst

        ///<summary>
        /// Gets the first instance of <see cref="T"/> from database
        /// or null if no instance of <see cref="T"/> has been stored
        ///</summary>
        T FindFirst();

        ///<summary>
        /// Gets the first instance of <see cref="T"/> from database
        /// or null if no instance of <see cref="T"/> has been stored
        ///</summary>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        T FindFirst(IDictionary<string, object> propertyValuePairs);

        ///<summary>
        /// Gets the first instance of <see cref="T"/> from database
        /// or null if no instance of <see cref="T"/> has been stored
        ///</summary>
        /// <param name="propertyOrderPairs">property name/<see cref="SortDirection"/> pairs which allow ordering</param>
        T FindFirst(IDictionary<string, SortDirection> propertyOrderPairs);

        ///<summary>
        /// Gets the first instance of <see cref="T"/> from database
        /// or null if no instance of <see cref="T"/> has been stored
        ///</summary>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        /// <param name="propertyOrderPairs">property name/<see cref="SortDirection"/> pairs which allow ordering</param>
        T FindFirst(IDictionary<string, object> propertyValuePairs, IDictionary<string, SortDirection> propertyOrderPairs);

        #endregion

        #region PagedFind

        ///<summary>
        /// Returns a page of all <see cref="T"/> instances stored in database.
        ///</summary>
        ///<param name="firstResult">first row selected from a full result set</param>
        ///<param name="pageSize">amount of objects returned</param>
        ///<param name="totalCount">amount of all <see cref="T"/> instances</param>
        IList<T> PagedFind(int firstResult, int pageSize, out long totalCount);

        ///<summary>
        /// Returns a page of all <see cref="T"/> instances stored in database.
        ///</summary>
        ///<param name="firstResult">first row selected from a full result set</param>
        ///<param name="pageSize">amount of objects returned</param>
        ///<param name="totalCount">amount of all <see cref="T"/> instances, which meet the criteria</param>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        IList<T> PagedFind(int firstResult, int pageSize, out long totalCount, IDictionary<string, object> propertyValuePairs);

        ///<summary>
        /// Returns a page of all <see cref="T"/> instances stored in database.
        ///</summary>
        ///<param name="firstResult">first row selected from a full result set</param>
        ///<param name="pageSize">amount of objects returned</param>
        ///<param name="totalCount">amount of all <see cref="T"/> instances, which meet the criteria</param>
        /// <param name="propertyOrderPairs">property name/<see cref="SortDirection"/> pairs which allow ordering</param>
        IList<T> PagedFind(int firstResult, int pageSize, out long totalCount, IDictionary<string, SortDirection> propertyOrderPairs);

        ///<summary>
        /// Returns a page of all <see cref="T"/> instances stored in database.
        ///</summary>
        ///<param name="firstResult">first row selected from a full result set</param>
        ///<param name="pageSize">amount of objects returned</param>
        ///<param name="totalCount">amount of all <see cref="T"/> instances, which meet the criteria</param>
        /// <param name="propertyValuePairs">property name/value pairs, which allow filtering</param>
        /// <param name="propertyOrderPairs">property name/<see cref="SortDirection"/> pairs which allow ordering</param>
        IList<T> PagedFind(int firstResult, int pageSize, out long totalCount, IDictionary<string, object> propertyValuePairs, IDictionary<string, SortDirection> propertyOrderPairs);

        #endregion
    }
}